home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / dpmigcc5.zip / RSX / SOURCE / PRINTF.C < prev    next >
C/C++ Source or Header  |  1994-12-12  |  8KB  |  348 lines

  1. /*****************************************************************************
  2.  * FILE: printf.c                                 *
  3.  *                                         *
  4.  * DESC:                                     *
  5.  *    - printf/puts library function                         *
  6.  *                                         *
  7.  * Copyright (C) 1993,1994                             *
  8.  *    Rainer Schnitker, Heeper Str. 283, 33607 Bielefeld             *
  9.  *    email: rainer@mathematik.uni-bielefeld.de                 *
  10.  *                                         *
  11.  *****************************************************************************/
  12.  
  13. #include <string.h>
  14. #include <stdarg.h>
  15. #include <sys\types.h>
  16. #include "DPMI.H"
  17. #include "PROCESS.H"
  18. #include "RMLIB.H"
  19. #include "RSX.H"
  20. #include "PRINTF.H"
  21.  
  22. static int vsprintf(char *, const char *, va_list);
  23. static int skip_atoi(const char **);
  24. static char *number(char *, long, int, int, int, int);
  25.  
  26. static int output(char *buf)
  27. {
  28.     char buf2[5 * 80];
  29.     char *s;
  30.     int i, j;
  31.  
  32.     if (rm_isatty(rsx_stdout)) {    /* console ? */
  33.     for (i = 0, j = 0; buf[i]; i++, j++) {
  34.         buf2[j] = buf[i];
  35.         if (buf2[j] == '\n')
  36.         buf2[++j] = '\r';
  37.     }
  38.     buf2[j] = '0';
  39.     s = buf2;
  40.     }
  41.     else {
  42.     s = buf;
  43.     j = i = strlen(buf);
  44.     }
  45.  
  46.     rm_write(rsx_stdout, s, j);
  47.     return i;
  48. }
  49.  
  50. int puts(char *s)
  51. {
  52.     int i;
  53.     i = output(s);
  54.     output("\n");
  55.     return i;
  56. }
  57.  
  58. int printf(const char *fmt,...)
  59. {
  60.     char buf[5 * 80];
  61.     va_list args;
  62.  
  63.     va_start(args, fmt);
  64.     vsprintf(buf, fmt, args);
  65.     va_end(args);
  66.  
  67.     return output(buf);
  68. }
  69.  
  70. int sprintf(char *buf, const char *fmt,...)
  71. {
  72.     va_list args;
  73.     int i;
  74.  
  75.     va_start(args, fmt);
  76.     i = vsprintf(buf, fmt, args);
  77.     va_end(args);
  78.     return i;
  79. }
  80.  
  81. /* ------------------------------------------------------------------------
  82. ** This code is modified from the Linux kernel code  (ver 0.99)
  83. **
  84. **  linux/kernel/vsprintf.c
  85. **
  86. **  Copyright (C) 1991, 1992  Linus Torvalds
  87. */
  88.  
  89. /* we use this so that we can do without the ctype library */
  90. #define is_digit(c)    ((c) >= '0' && (c) <= '9')
  91.  
  92. static int skip_atoi(const char **s)
  93. {
  94.     int i = 0;
  95.  
  96.     while (is_digit(**s))
  97.     i = i * 10 + *((*s)++) - '0';
  98.     return i;
  99. }
  100.  
  101. #define ZEROPAD 1        /* pad with zero */
  102. #define SIGN    2        /* unsigned/signed long */
  103. #define PLUS    4        /* show plus */
  104. #define SPACE    8        /* space if plus */
  105. #define LEFT    16        /* left justified */
  106. #define SPECIAL 32        /* 0x */
  107. #define SMALL    64        /* use 'abcdef' instead of 'ABCDEF' */
  108.  
  109. #ifdef __EMX__
  110. #define do_div(n,base) ({      \
  111. int __res; \              \
  112. __asm__("divl %4"                 \
  113.     :"=a" (n), "=d" (__res)       \
  114.     :"0" (n),"1" (0),"r" (base)); \
  115. __res; })
  116. #else
  117. #define do_div(n,base) ({ \
  118.     unsigned long _res = (unsigned long) n % (unsigned long) base; \
  119.     n = (unsigned long) n / (unsigned long) base; \
  120.     (unsigned) _res; })
  121. #endif
  122.  
  123. static char *
  124.  number(char *str, long num, int base, int size, int precision, int type)
  125. {
  126.     char c, sign, tmp[36];
  127.     const char *digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  128.     int i;
  129.  
  130.     if (type & SMALL)
  131.     digits = "0123456789abcdefghijklmnopqrstuvwxyz";
  132.     if (type & LEFT)
  133.     type &= ~ZEROPAD;
  134.     if (base < 2 || base > 36)
  135.     return 0;
  136.     c = (type & ZEROPAD) ? '0' : ' ';
  137.     if (type & SIGN && num < 0) {
  138.     sign = '-';
  139.     num = -num;
  140.     } else
  141.     sign = (type & PLUS) ? '+' : ((type & SPACE) ? ' ' : 0);
  142.     if (sign)
  143.     size--;
  144.     if (type & SPECIAL)
  145.     if (base == 16)
  146.         size -= 2;
  147.     else if (base == 8)
  148.         size--;
  149.     i = 0;
  150.     if (num == 0)
  151.     tmp[i++] = '0';
  152.     else
  153.     while (num != 0) {
  154.         unsigned long _res = (unsigned long) num % (unsigned long) base;
  155.         num = (unsigned long) num / (unsigned long) base;
  156.         tmp[i++] = digits[_res];
  157.     }
  158.     if (i > precision)
  159.     precision = i;
  160.     size -= precision;
  161.     if (!(type & (ZEROPAD + LEFT)))
  162.     while (size-- > 0)
  163.         *str++ = ' ';
  164.     if (sign)
  165.     *str++ = sign;
  166.     if (type & SPECIAL)
  167.     if (base == 8)
  168.         *str++ = '0';
  169.     else if (base == 16) {
  170.         *str++ = '0';
  171.         *str++ = digits[33];
  172.     }
  173.     if (!(type & LEFT))
  174.     while (size-- > 0)
  175.         *str++ = c;
  176.     while (i < precision--)
  177.     *str++ = '0';
  178.     while (i-- > 0)
  179.     *str++ = tmp[i];
  180.     while (size-- > 0)
  181.     *str++ = ' ';
  182.     return str;
  183. }
  184.  
  185. static int vsprintf(char *buf, const char *fmt, va_list args)
  186. {
  187.     int len;
  188.     int i;
  189.     char *str;
  190.     char *s;
  191.     int *ip;
  192.  
  193.     int flags;            /* flags to number() */
  194.  
  195.     int field_width;        /* width of output field */
  196.     int precision;        /* min. # of digits for integers; max number
  197.                  * of chars for from string */
  198.     int qualifier;        /* 'h', 'l', or 'L' for integer fields */
  199.     int use_long;
  200.  
  201.     for (str = buf; *fmt; ++fmt) {
  202.     if (*fmt != '%') {
  203.         *str++ = *fmt;
  204.         continue;
  205.     }
  206.     /* process flags */
  207.     flags = 0;
  208.     use_long = 0;
  209.       repeat:
  210.     ++fmt;            /* this also skips first '%' */
  211.     switch (*fmt) {
  212.     case '-':
  213.         flags |= LEFT;
  214.         goto repeat;
  215.     case '+':
  216.         flags |= PLUS;
  217.         goto repeat;
  218.     case ' ':
  219.         flags |= SPACE;
  220.         goto repeat;
  221.     case '#':
  222.         flags |= SPECIAL;
  223.         goto repeat;
  224.     case '0':
  225.         flags |= ZEROPAD;
  226.         goto repeat;
  227.     }
  228.  
  229.     /* get field width */
  230.     field_width = -1;
  231.     if (is_digit(*fmt))
  232.         field_width = skip_atoi(&fmt);
  233.     else if (*fmt == '*') {
  234.         /* it's the next argument */
  235.         field_width = va_arg(args, int);
  236.         if (field_width < 0) {
  237.         field_width = -field_width;
  238.         flags |= LEFT;
  239.         }
  240.     }
  241.     /* get the precision */
  242.     precision = -1;
  243.     if (*fmt == '.') {
  244.         ++fmt;
  245.         if (is_digit(*fmt))
  246.         precision = skip_atoi(&fmt);
  247.         else if (*fmt == '*') {
  248.         /* it's the next argument */
  249.         precision = va_arg(args, int);
  250.         }
  251.         if (precision < 0)
  252.         precision = 0;
  253.     }
  254.     /* get the conversion qualifier */
  255.     qualifier = -1;
  256.     if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
  257.         if (*fmt != 'h')
  258.         use_long = 1;
  259.         qualifier = *fmt;
  260.         ++fmt;
  261.     }
  262.     switch (*fmt) {
  263.     case 'c':
  264.         if (!(flags & LEFT))
  265.         while (--field_width > 0)
  266.             *str++ = ' ';
  267.         *str++ = (unsigned char) va_arg(args, int);
  268.         while (--field_width > 0)
  269.         *str++ = ' ';
  270.         break;
  271.  
  272.     case 's':
  273.         s = va_arg(args, char *);
  274.         len = strlen(s);
  275.         if (precision < 0)
  276.         precision = len;
  277.         else if (len > precision)
  278.         len = precision;
  279.  
  280.         if (!(flags & LEFT))
  281.         while (len < field_width--)
  282.             *str++ = ' ';
  283.         for (i = 0; i < len; ++i)
  284.         *str++ = *s++;
  285.         while (len < field_width--)
  286.         *str++ = ' ';
  287.         break;
  288.  
  289.     case 'o':
  290.         if (use_long)
  291.         str = number(str, (long) va_arg(args, unsigned long), 8,
  292.                  field_width, precision, flags);
  293.         else
  294.         str = number(str, (long) va_arg(args, unsigned), 8,
  295.                  field_width, precision, flags);
  296.         break;
  297.  
  298.     case 'p':
  299.         if (field_width == -1) {
  300.         field_width = 8;
  301.         flags |= ZEROPAD;
  302.         }
  303.         str = number(str, (long) va_arg(args, void *), 16,
  304.              field_width, precision, flags);
  305.         break;
  306.  
  307.     case 'x':
  308.         flags |= SMALL;
  309.     case 'X':
  310.         if (use_long)
  311.         str = number(str, (long) va_arg(args, unsigned long), 16,
  312.                  field_width, precision, flags);
  313.         else
  314.         str = number(str, (long) va_arg(args, unsigned), 16,
  315.                  field_width, precision, flags);
  316.         break;
  317.  
  318.     case 'd':
  319.     case 'i':
  320.         flags |= SIGN;
  321.     case 'u':
  322.         if (use_long)
  323.         str = number(str, (long) va_arg(args, unsigned long), 10,
  324.                  field_width, precision, flags);
  325.         else
  326.         str = number(str, (long) va_arg(args, unsigned), 10,
  327.                  field_width, precision, flags);
  328.         break;
  329.  
  330.     case 'n':
  331.         ip = va_arg(args, int *);
  332.         *ip = (str - buf);
  333.         break;
  334.  
  335.     default:
  336.         if (*fmt != '%')
  337.         *str++ = '%';
  338.         if (*fmt)
  339.         *str++ = *fmt;
  340.         else
  341.         --fmt;
  342.         break;
  343.     }
  344.     }
  345.     *str = '\0';
  346.     return str - buf;
  347. }
  348.